#include <window_manager.h>
#include <stdexcept>
#include <string>
#include <debug.h>
#include <imgui.h>
#include <imgui_impl_sdl.h>
#include <imgui_impl_sdlrenderer.h>

WindowManager::WindowManager(std::int32_t w, std::int32_t h,  const std::string& t)
    : height(h), width(w), title(t), mTexture(nullptr), mWindow(nullptr), mRenderer(nullptr) {
    mWindow = 
        SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
                            width, height, SDL_WINDOW_SHOWN);
    CheckNullPtr(mWindow);

    mRenderer = 
        SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED);
    CheckNullPtr(mRenderer);

    mTexture = 
        SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
    CheckNullPtr(mTexture);

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;

    ImGui::StyleColorsDark();

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForSDLRenderer(mWindow, mRenderer);
    ImGui_ImplSDLRenderer_Init(mRenderer);
}

void WindowManager::newFrame() {
    ImGui_ImplSDLRenderer_NewFrame();
    ImGui_ImplSDL2_NewFrame();
    ImGui::NewFrame();
}

void WindowManager::clear(const Color4f& color) {
    CheckFunc(SDL_SetRenderDrawColor(mRenderer, 
        static_cast<std::uint8_t>(color.r * 255.0f), 
        static_cast<std::uint8_t>(color.g * 255.0f), 
        static_cast<std::uint8_t>(color.b * 255.0f), 
        static_cast<std::uint8_t>(color.a * 255.0f)));
    CheckFunc(SDL_RenderClear(mRenderer));
}

void WindowManager::swap(const std::uint8_t* image) {
    ImGui::Render();
    CheckFunc(SDL_UpdateTexture(mTexture, NULL, image, sizeof(std::uint8_t) * 4 * width));
    CheckFunc(SDL_RenderCopy(mRenderer, mTexture, nullptr, nullptr));
    ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
    SDL_RenderPresent(mRenderer);
}

WindowManager::~WindowManager() noexcept {
    ImGui_ImplSDLRenderer_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();
    SDL_DestroyRenderer(mRenderer);
    SDL_DestroyWindow(mWindow);
}